<script setup lang="ts">
  import { ref, computed, defineAsyncComponent, useAttrs } from "vue";
  import { ElDialog } from "element-plus";
  import { objDiff, clo } from "@/util";
  import user from "@/components/sql/user.vue";

  type TypeElDialog = CPN<typeof ElDialog>;
  interface Props extends /* @vue-ignore */ TypeElDialog {
    appendToBody?: boolean;
    zIndex?: number;
  }
  type Types = keyof Omit<typeof gd, "groupTree" | "goodsTypeTree">;
  let source: any, curd: gt.curd = 0;
  const
    props = withDefaults(defineProps<Props>(), { appendToBody: true, zIndex: 3 }),
    ua = useAttrs(),
    attrs = computed(() => {
      return { ...props, ...ua };
    }),
    data = ref(),
    show = ref(false),
    disabled = ref(false),
    dialogTitle = ref(""),
    entity = ref<InstanceType<typeof user>>(),
    emit = defineEmits<{ (e: "confirm"): void; }>(),
    cmpType = ref<Types>("group"),
    cmp = computed(() => {
      switch (cmpType.value) {
        case "goodsType": return defineAsyncComponent(() => import("./goodsType.vue"));
        case "goods": return defineAsyncComponent(() => import("./goods.vue"));
        case "group": return defineAsyncComponent(() => import("./group.vue"));
        case "msg": return defineAsyncComponent(() => import("./msg.vue"));
        case "order": return defineAsyncComponent(() => import("./order.vue"));
        case "setting": return defineAsyncComponent(() => import("./setting.vue"));
        case "stock": return defineAsyncComponent(() => import("./stock.vue"));
        case "stockLog": return defineAsyncComponent(() => import("./stockLog.vue"));
        case "upload": return defineAsyncComponent(() => import("./upload.vue"));
        case "user": return defineAsyncComponent(() => import("./user.vue"));
        case "prize": return defineAsyncComponent(() => import("./prize.vue"));
        case "prizeGroup": return defineAsyncComponent(() => import("./prizeGroup.vue"));
        case "transfer": return defineAsyncComponent(() => import("./transfer.vue"));
        case "voucher": return defineAsyncComponent(() => import("./voucher.vue"));

        default:
          break;
      }
    });
  let cbk: cbk;
  async function confirm() {
    if (disabled.value || await entity.value?.validate()) {
      show.value = false;
      if (curd != 2) {
        const t = curd == 1 ? objDiff(source, data.value, 1) : undefined;
        const d: any = gd[cmpType.value];
        let r: any;
        switch (curd) {
          case 0: r = await d.create(data.value); break;
          case 1: r = t ? (await d.update(Object.assign(t, { id: source.id }))) : 0; break;
          case 3: r = await d.delete({ id: source.id }); break;
          default:
            return;
        }
        if (r) {
          if (curd == 1) {
            Object.assign(source, data.value);
          }
          msg(typeof r == "string" ? r : `${dialogTitle.value}成功`, "success");
          emit("confirm");
        }
        if (cbk instanceof Function) {
          cbk(r);
        }
      }
    }
  }
  function reset() {
    entity.value?.resetFields();
    data.value = clo(source);
  }
  function open<T extends Types>(type: T, method: gt.curd, value: (typeof gd[T])[number], title = "用户") {
    cmpType.value = type;
    curd = method;
    dialogTitle.value = props.title || (["添加", "修改", "查看", "删除"][curd] + title);
    disabled.value = curd > 1;
    source = value;
    data.value = clo(source);
    show.value = true;
    return new Promise<any>((resolve) => {
      cbk = resolve;
    });
  }
  defineExpose({ open });
</script>
<template>
  <ElDialog v-if="show" class="Dialog" :="attrs" :title="dialogTitle" v-model="show">
    <component :is="cmp" v-model="data" :disabled="disabled" ref="entity" />
    <template v-if="!$slots.footer" #footer>
      <el-button type="success" @click="reset" v-if="!disabled">重置</el-button>
      <el-button type="primary" @click="confirm">确定</el-button>
    </template>
  </ElDialog>
</template>